package com.cheng.gmall.item.service.impl;

import com.cheng.gmall.common.config.constant.RedisConst;
import com.cheng.gmall.item.aspect.MallCache;
import com.cheng.gmall.item.feign.SkuDetailFeignClient;
import com.cheng.gmall.item.service.CacheService;
import com.cheng.gmall.item.service.SkuDetailService;
import com.cheng.gmall.product.entity.SkuImage;
import com.cheng.gmall.product.entity.SkuInfo;
import com.cheng.gmall.product.entity.SpuSaleAttr;
import com.cheng.gmall.product.vo.CategoryTreeVo;
import com.cheng.gmall.product.vo.SkuDetailVo;
import com.cheng.gmall.product.vo.SkuDetailVo.CategoryViewDTO;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * SkuDetailServiceImpl为SkuDetailService的实现类，用于获取商品详情数据
 */
@Slf4j
@Service
public class SkuDetailServiceImpl implements SkuDetailService {


    @Autowired
    SkuDetailFeignClient skuDetailFeignClient;
    @Autowired
    ThreadPoolExecutor coreExecutor;
    @Autowired
    CacheService cacheService;
    @Autowired
    RedissonClient redissonClient;
    /**
     * 获取商品详情数据
     *
     * @param skuId 商品ID
     * @return 包含商品详情数据的SkuDetailVo对象
     */
    @Autowired
    StringRedisTemplate redisTemplate;

    //只关注业务，增强逻辑由切面执行
    //允许
    @MallCache(cacheKey = RedisConst.SKU_DETAIL_CACHE + "#{args[0]}",
            bitMapName = RedisConst.SKUID_BITMAP,
            bitMapKey = "#{args[0]}",
            lockKey = RedisConst.SKU_LOCK + "#{args[0]}}",
            ttl = 7,
            unit = TimeUnit.DAYS
    )
    @Override
    public SkuDetailVo getSkuDetailData(Long skuId) {
        return getDataFromRpc(skuId);
    }


//    public SkuDetailVo getSkuDetailDataWithDistLcok(Long skuId) throws InterruptedException {
//
//        SkuDetailVo data = getDataFromRpc(skuId);
//        SkuDetailVo cache = cacheService.getFromCache(skuId);
//        if (cache != null) {
//            //缓存有 直接返回
//        }
//        //缓存没有，准备回源
//        //先问bitmap有没有这个商品
//        boolean mightContain = cacheService.mightContain(skuId);
//        if (!mightContain) {
//            //bitmap不包含，直接返回空
//            return null;
//        }
//        //bitmap有  去数据库查  防止缓存击穿  查之前加锁
//        //锁的粒度要细
//        RLock lock = redissonClient.getLock(RedisConst.SKU_LOCK + skuId);
//        boolean tryLock = false;
//        //加锁  尝试加锁
//        try {
//            tryLock = lock.tryLock();
//            if (tryLock) {
//                //得到锁，回源
//                cache = getDataFromRpc(skuId);
//
//                cacheService.saveData(skuId, cache);
//                return cache;
//            } else {
//                TimeUnit.MILLISECONDS.sleep(300);
//                return cacheService.getFromCache(skuId);
//            }
//        } finally {
//            if (tryLock) {
//                try {
//                    lock.unlock();
//                } catch (Exception e) {
//                }
//            }
//
//        }
//
//
//    }
//    @Override
//    public SkuDetailVo getSkuDetailDataLocalLock(Long skuId) {
//
//
//        SkuDetailVo returnVal = null;
//
//        //1.查缓存
//        returnVal = cacheService.getFromCache(skuId);
//        //一定要能判断出真没有还是假没有
//        if (returnVal == null) {
//            //2.位图判断是否有
//            log.info("查询缓存开始");
//            boolean contain = cacheService.mightContain(skuId);
//            if (!contain) {
//                log.info("疑似攻击请求");
//                return null;
//            }
//            //3.缓存没有，回源
//            log.info("bitmap有,准备回源");
//
//            //准备拦截击穿风险
//            //AQS和CAS的区别
//            ReentrantLock lock = new ReentrantLock();
//            //瞬间抢锁
//            boolean tryLock = lock.tryLock();
//            if (tryLock) {
//                log.info("加锁成功,正在回源");
//                //4.抢锁成功
//                returnVal = getDataFromRpc(skuId);
//                //5.保存到缓存;null缓存都可能不会被调用; 如果用的布隆过滤器，可能会误判，即使误判，放给数据库没有，也要null值返回
//                cacheService.saveData(skuId, returnVal);
//                lock.unlock();
//
//            } else {
//                //6.抢锁失败后，直接看缓存
//                try {
//                    TimeUnit.MILLISECONDS.sleep(500);
//                    returnVal = cacheService.getFromCache(skuId);
//
//                } catch (InterruptedException e) {
//                    throw new RuntimeException(e);
//                }
//            }
//        }
//        return returnVal;
//    }

//    @Override
//    public SkuDetailVo getSkuDetailDataBullSave(Long skuId) {
//        // 获取SKU详情数据的方法
//        // 先查缓存 sku：info：49==商品json
//        String json = redisTemplate.opsForValue().get("sku:info:" + skuId);
//        if (StringUtils.isEmpty(json)) {
//
//            synchronized (this) {
//                //先看缓存
//                SkuDetailVo result = getDataFromRpc(skuId);
//                String JsonData = "x";
//                if (result == null) {
//                    JsonData = JSON.toJSONString(result);
//                }
//                redisTemplate.opsForValue().set("sku:info:" + skuId, JsonData, 7, TimeUnit.DAYS);
//                return result;
//            }
//            // 如果缓存中不存在，从远程RPC获取数据，并将结果存入缓存
//
//        }
//
//        // 如果缓存中存在，直接从缓存中获取数据
//        //4.缓存中有
//        if ("x".equals(json)) {
//            return null;
//        }
//        return JSON.parseObject(json, SkuDetailVo.class);
//
//    }


//    //时间复杂度o1
//    private Map<Long, SkuDetailVo> cache = new ConcurrentHashMap<>();
//
//
//    public SkuDetailVo getSkuDetailDataLocalCache(Long skuId) {
//        //1.先查缓存
//        SkuDetailVo result = cache.get(skuId);
//        //2.缓存中没有
//        if (result == null) {
//
//            //回源：回到数据源头进行查询
//            result = getDataFromRpc(skuId);
//            //把数据同步到缓存
//            cache.put(skuId, result);
//        }
//
//        return result;
//
//    }


    private SkuDetailVo getDataFromRpc(Long skuId) {
        CountDownLatch countDownLatch = new CountDownLatch(6);
        //TODO 获取商品详情数据
        SkuDetailVo data = new SkuDetailVo();
        //1.异步：商品详情【图片】//自定义的线程池
        CompletableFuture<SkuInfo> skuInfoFuture = CompletableFuture.supplyAsync(() -> {
            SkuInfo skuInfo = skuDetailFeignClient.getSkuInfo(skuId).getData();
            return skuInfo;
        }, coreExecutor);
        //2、异步：图片
        CompletableFuture<Void> imageFuture = skuInfoFuture.thenAcceptAsync((result) -> {
            if (result == null) return;
            List<SkuImage> skuImages = skuDetailFeignClient.getSkuImages(skuId).getData();
            result.setSkuImageList(skuImages);
            data.setSkuInfo(result);
        }, coreExecutor);


        //3、当前商品精确完整分类信息；
        CompletableFuture<Void> CategoryFuture = skuInfoFuture.thenAcceptAsync(res -> {
            if (res == null) return;
            CategoryTreeVo categoryTreeVo = skuDetailFeignClient.getCategoryTreeWithC3Id(res.getCategory3Id()).getData();
            //数据模型转换
            CategoryViewDTO viewDTO = convertToCategoryViewDTO(categoryTreeVo);
            data.setCategoryView(viewDTO);
        }, coreExecutor);
        //4、实时价格

        CompletableFuture<Void> PriceFuture = CompletableFuture.runAsync(() -> {
            try {
                BigDecimal price = skuDetailFeignClient.getPrice(skuId).getData();
                data.setPrice(price);
            } catch (Exception e) {

            }

        }, coreExecutor);


        //5、销售属性;
        CompletableFuture<Void> saleAttrFuture = skuInfoFuture.thenAcceptAsync(res -> {
            if (res == null) return;
            List<SpuSaleAttr> spuSaleAttrs = skuDetailFeignClient.getSpuSaleAttr(res.getSpuId(), skuId).getData();
            data.setSpuSaleAttrList(spuSaleAttrs);
        }, coreExecutor);


        //5、当前sku的所有兄弟们的所有组合可能性。

        CompletableFuture<Void> ValueJsonFuture = skuInfoFuture.thenAccept(res -> {
            if (res == null) return;
            String json = skuDetailFeignClient.getValuesSkuJson(res.getSpuId()).getData();
            data.setValuesSkuJson(json);
        });
//等待所有任务都完成
        CompletableFuture.allOf(imageFuture, CategoryFuture, PriceFuture, saleAttrFuture, ValueJsonFuture).join();
        return data;
    }

    /**
     * 将CategoryTreeVo对象转换为CategoryViewDTO对象
     *
     * @param categoryTreeVo 包含商品分类树信息的CategoryTreeVo对象
     * @return 转换后的CategoryViewDTO对象
     */
    private CategoryViewDTO convertToCategoryViewDTO(CategoryTreeVo categoryTreeVo) {
        CategoryViewDTO viewDTO = new CategoryViewDTO();
        viewDTO.setCategory1Id(categoryTreeVo.getCategoryId());
        viewDTO.setCategory1Name(categoryTreeVo.getCategoryName());

        CategoryTreeVo child1 = categoryTreeVo.getCategoryChild().get(0);
        viewDTO.setCategory2Id(child1.getCategoryId());
        viewDTO.setCategory2Name(child1.getCategoryName());

        CategoryTreeVo child2 = child1.getCategoryChild().get(0);
        viewDTO.setCategory3Id(child2.getCategoryId());
        viewDTO.setCategory3Name(child2.getCategoryName());
        return viewDTO;
    }


}
